home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 1998 June
/
SGI Freeware 1998 June.iso
/
dist
/
fw_UMINNgopher.idb
/
usr
/
freeware
/
src
/
gopher_1.12
/
object
/
GSgopherobj.c.z
/
GSgopherobj.c
Wrap
Text File
|
1997-09-09
|
10KB
|
514 lines
/********************************************************************
* $Author: drich $
* $Revision: 1.1 $
* $Date: 1995/10/03 04:09:44 $
* $Source: /proj/freeware1.0/gopher1.12/src/object/RCS/GSgopherobj.c,v $
* $Status: $
*
* Paul Lindner, University of Minnesota CIS.
*
* Copyright 1991, 1992 by the Regents of the University of Minnesota
* see the file "Copyright" in the distribution for conditions of use.
*********************************************************************
* MODULE: GSgopherobj.c
* Implement gopher directory functions.
*********************************************************************
* Revision History:
* $Log: GSgopherobj.c,v $
* Revision 1.1 1995/10/03 04:09:44 drich
* gopher 1.2 check-in
*
* Revision 1.1.1.3 1993/01/11 19:54:06 lindner
* Fixed syntax in UCX #defines. (DuH!)
*
* Revision 1.1.1.2 1993/01/08 19:00:00 lindner
* Mods for UCX
*
* Revision 1.1.1.1 1992/12/31 05:01:31 lindner
* Chnages for VMS.
*
* Revision 1.1 1992/12/17 21:03:54 jqj
* Initial revision
*
* Revision 1.1 1992/12/10 23:27:52 lindner
* gopher 1.1 release
*
*
*********************************************************************/
#include "GSgopherobj.h"
#if defined(mips) && defined(ultrix) /*** Gross hack, yuck! ***/
#define _SIZE_T
#endif
#include "String.h"
#include <stdio.h>
#include "compatible.h"
extern int DEBUG;
/*
* These are needed for GSconnect(). Ick.
*/
#ifdef VMS
#include <socket.h>
#include <in.h>
#include <file.h>
#include <inet.h>
#include <netdb.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/file.h>
#ifndef hpux
#include <arpa/inet.h>
#endif
#include <netdb.h>
#endif /* not VMS */
#include "Malloc.h"
/*
* Make a new gopherobj, set the fields accordingly...
*/
GopherObj *
GSnewSet(objtype, Title, Selstr, Host, Port)
char objtype;
char *Title;
char *Selstr;
char *Host;
int Port;
{
GopherObj *temp;
temp = (GopherObj *) malloc(sizeof(GopherObj));
temp->Selstr = STRnewSet(Selstr);
temp->Title = STRnewSet(Title);
temp->Host = STRnewSet(Host);
temp->iPort = Port;
GSsetNum(temp, -1);
GSsetWeight(temp, 0);
return(temp);
}
/*
* Make a new gopherobj... Should reuse destroyed GopherObjs...
*/
GopherObj *
GSnew()
{
GopherObj *temp;
temp = (GopherObj *) malloc(sizeof(GopherObj));
temp->Selstr = STRnew();
temp->Title = STRnew();
temp->Host = STRnew();
GSinit(temp);
return(temp);
}
void
GSdestroy(gs)
GopherObj *gs;
{
STRdestroy(gs->Selstr);
STRdestroy(gs->Title);
STRdestroy(gs->Host);
free(gs);
}
/*
* Clear out all the crud
*/
void
GSinit(gs)
GopherObj *gs;
{
GSsetType(gs, '\0');
STRinit(gs->Title);
STRinit(gs->Selstr);
STRinit(gs->Host);
gs->iPort = 0;
GSsetNum(gs, -1);
GSsetWeight(gs, 0);
}
void
GStoNet(gs, sockfd)
GopherObj *gs;
int sockfd;
{
static char buf[1024];
buf[0] = GSgetType(gs);
sprintf(buf + 1, "%s\t%s\t%s\t%d\r\n",
GSgetTitle(gs),
GSgetPath(gs),
GSgetHost(gs),
GSgetPort(gs));
writestring(sockfd, buf);
if (DEBUG)
fprintf(stderr, buf);
}
void
GStoNetHTML(gs, sockfd)
GopherObj *gs;
int sockfd;
{
static char buf[1024];
static char pathbuf[1024];
buf[0] = '\0';
pathbuf[0] = '\0';
/** Convert Path so that spaces are %20 **/
Tohexstr(GSgetPath(gs), pathbuf);
sprintf(buf, "<A HREF=http://%s:%d/%s>%s</A>",
GSgetHost(gs),
GSgetPort(gs),
pathbuf,
GSgetTitle(gs));
writestring(sockfd, buf);
if (DEBUG)
fprintf(stderr, "HTML: %s", buf);
if (GSgetWeight(gs) != 0) {
sprintf(buf, "Score: %d\r\n", GSgetWeight(gs));
writestring(sockfd, buf);
}
else
writestring(sockfd, "\r\n");
}
/*
* Fill in a GopherObj, given an HREF= link from a WWW anchor..
* So far only works with http
*/
void
GSfromHREF(gs, href)
GopherObj *gs;
char *href;
{
char *cp;
char *host;
char path[1024];
if (strncasecmp(href, "http://", 7)==0) {
host = href +7;
cp = strchr(href+7, '/');
if (cp == NULL)
return;
*cp = '\0';
strcpy(path, "GET ");
strcat(path, cp+1);
GSsetPath(gs, path);
GSsetType(gs, 'h');
GSsetPath(gs, path);
cp = strchr(host, ':');
if (cp==NULL)
GSsetPort(gs, 80); /** default WWW port **/
else {
GSsetPort(gs, atoi(cp+1));
*cp = '\0';
}
GSsetHost(gs, host);
}
}
extern int readfield();
extern int readline();
int
GSfromNet(gs, sockfd)
GopherObj *gs;
int sockfd;
{
char foo[1024];
if (readfield(sockfd, foo, 1024)<= 0) {
/* EOF or error */
return(-1);
}
GSsetType(gs, foo[0]);
/** Get the kind of file from the first character **/
/** Filter out files that we can't deal with **/
switch (GSgetType(gs)) {
case A_FILE:
case A_DIRECTORY:
case A_MACHEX:
case A_PCBIN:
case A_CSO:
case A_INDEX:
case A_TELNET:
case A_SOUND:
case A_UNIXBIN:
case A_GIF:
case A_HTML:
case A_TN3270:
case A_MIME:
case A_IMAGE:
break;
case A_EOI:
if (foo[1] == '\r' && foo[2] == '\n')
return(1);
default:
return(-2);
}
/** Suck off the User Displayable name **/
GSsetTitle(gs, foo+1);
/** Suck off the Pathname **/
if (readfield(sockfd, foo, 1024) == 0)
return(-1);
GSsetPath(gs, foo);
/** Suck off the hostname **/
if (readfield(sockfd, foo, 1024) == 0)
return(-1);
GSsetHost(gs, foo);
if (readline(sockfd, foo, 1024)==0)
return(-1);
GSsetPort(gs, 0);
/** Get the port number **/
GSsetPort(gs, atoi(foo));
return(0);
}
/** Copy a GopherObj ***/
void
GScpy(dest, orig)
GopherObj *dest, *orig;
{
dest->sFileType = orig->sFileType;
dest->iPort = orig->iPort;
dest->Itemnum = orig->Itemnum;
GSsetTitle(dest, GSgetTitle(orig));
GSsetPath(dest, GSgetPath(orig));
GSsetHost(dest, GSgetHost(orig));
}
/** Compare two GopherObjs ***/
int
GScmp(gs1, gs2)
GopherObj *gs1, *gs2;
{
if (GSgetTitle(gs1) == NULL)
return(1);
if (GSgetTitle(gs2) == NULL)
return(-1);
return(strcmp(GSgetTitle(gs1), GSgetTitle(gs2)));
}
/* GSconnect performs a connection to socket 'service' on host
* 'host'. Host can be a hostname or ip-address. If 'host' is null, the
* local host is assumed. The parameter full_hostname will, on return,
* contain the expanded hostname (if possible). Note that full_hostname is a
* pointer to a char *, and is allocated by connect_to_gopher()
*
* Errors:
*
* -1 get service failed
*
* -2 get host failed
*
* -3 socket call failed
*
* -4 connect call failed
*/
int
GSconnect(gs)
GopherObj *gs;
{
struct sockaddr_in Server;
struct hostent *HostPtr;
int iSock = 0;
int ERRinet = -1;
#ifdef _CRAY
ERRinet = 0xFFFFFFFF; /* -1 doesn't sign extend on 64 bit machines */
#endif
/*** Find the hostname address ***/
if ((Server.sin_addr.s_addr = inet_addr(GSgetHost(gs))) == ERRinet) {
if (HostPtr = gethostbyname(GSgetHost(gs))) {
bzero((char *) &Server, sizeof(Server));
bcopy(HostPtr->h_addr, (char *) &Server.sin_addr, HostPtr->h_length);
Server.sin_family = HostPtr->h_addrtype;
} else
return (-2);
} else
Server.sin_family = AF_INET;
Server.sin_port = (unsigned short) htons(GSgetPort(gs));
/*** Open the socket ***/
if ((iSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return (-3);
#ifndef UCX
setsockopt(iSock, SOL_SOCKET, ~SO_LINGER, 0, 0);
#endif
setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, 0, 0);
setsockopt(iSock, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
/*** Connect ***/
if (connect(iSock, (struct sockaddr *) &Server, sizeof(Server)) < 0) {
closenet(iSock);
return (-4);
}
return(iSock);
}
/*
* GSfromLink takes an open file descriptor and starts reading from it.
* It keeps going until it findsL
* enough fields for a gopherobj
* no data left
*
* returns 0 with success, -1 on an error.
*/
#define G_PATH (1<<0)
#define G_TYPE (1<<1)
#define G_NAME (1<<2)
#define G_PORT (1<<3)
#define G_HOST (1<<4)
#define G_ALL (G_PATH | G_TYPE | G_NAME | G_PORT | G_HOST)
int
GSfromLink(gs, fd, host, port)
GopherObj *gs;
int fd;
char *host;
int port;
{
int doneflags = 0;
char buf[1024];
while ((doneflags != G_ALL) && readline(fd, buf, 1024)) {
if (buf[0] == '#')
continue; /* comment */
ZapCRLF(buf);
if (strncmp(buf, "Type=", 5)==0) {
GSsetType(gs, buf[5]);
doneflags |= G_TYPE;
}
if (strncmp(buf, "Name=", 5)==0) {
GSsetTitle(gs, buf+5);
doneflags |= G_NAME;
}
if (strncmp(buf, "Path=", 5)==0) {
GSsetPath(gs, buf+5);
doneflags |= G_PATH;
}
if (strncmp(buf, "Host=", 5)==0) {
if (buf[5] == '+' && buf[6] == '\0')
GSsetHost(gs, host);
else
GSsetHost(gs, buf+5);
doneflags |= G_HOST;
}
if (strncmp(buf, "Port=", 5)==0) {
if (buf[5] == '+' && buf[6] == '\0')
GSsetPort(gs, port);
else
GSsetPort(gs, atoi(buf+5));
doneflags |= G_PORT;
}
if (strncmp(buf, "Numb=", 5)==0)
GSsetNum(gs, atoi(buf+5));
}
return ((doneflags == G_ALL) ? 0 : -1); /* 0 == success */
}
void
GStoLink(gs, fd)
GopherObj *gs;
int fd;
{
char gtype[2];
char portnum[16];
gtype[0] = GSgetType(gs);
gtype[1] = '\0';
writestring(fd, "#");
writestring(fd, "\nType=");
writestring(fd, gtype);
writestring(fd, "\nName=");
writestring(fd, GSgetTitle(gs));
writestring(fd, "\nPath=");
writestring(fd, GSgetPath(gs));
writestring(fd, "\nHost=");
writestring(fd, GSgetHost(gs));
writestring(fd, "\nPort=");
sprintf(portnum, "%d", GSgetPort(gs));
writestring(fd, portnum);
writestring(fd, "\n");
}